Flink、SparkStream和Storm对比

概述

Flink、Spark Streaming、Storm都可以进行实时计算,但各有特点。

在大数据处理领域,批处理任务和流处理任务一般被认为是两种不同的任务,一个大数据框架一般会被设计为只能处理其中一种任务。例如Storm只支持流处理任务,而MapReduce、Spark只支持批处理任务。Spark Streaming是采用了一种micro-batch的架构,即把输入的数据流且分为细粒度的batch,并为每一个batch数据提交一个批处理的Spark任务,所以Spark Streaming本质上还是基于Spark批处理系统对流式数据进行处理,和Storm等完全流式的数据处理方式完全不同。

Flink通过灵活的执行引擎,能够同时支持批处理任务和流处理任务。在执行引擎这一层,流处理系统与批处理系统最大的不同在于节点间的数据传输方式。对于一个流处理系统,其节点间数据传输的标准模型是:当一条数据被处理完成后,序列化到缓存中,然后立刻通过网络传输到下一个节点,由下一个节点继续处理。而对于一个批处理系统,其节点间数据传输的标准模型是:当一条数据被处理完成后,序列化到缓存中,并不会立刻通过网络传输到下一个节点,当缓存写满,就持久化到本地硬盘上,当所有数据都被处理完成后,才开始将处理后的数据通过网络传输到下一个节点。这两种数据传输模式是两个极端,对应的是流处理系统对低延迟的要求和批处理系统对高吞吐量的要求。

Flink的执行引擎采用了一种十分灵活的方式,同时支持了这两种数据传输模型。

Flink以固定的缓存块为单位进行网络数据传输,用户可以通过设置缓存块超时值指定缓存块的传输时机。如果缓存块的超时值为0,则Flink的数据传输方式类似上文所提到流处理系统的标准模型,此时系统可以获得最低的处理延迟。如果缓存块的超时值为无限大,则Flink的数据传输方式类似上文所提到批处理系统的标准模型,此时系统可以获得最高的吞吐量。同时缓存块的超时值也可以设置为0到无限大之间的任意值。缓存块的超时阈值越小,则Flink流处理执行引擎的数据处理延迟越低,但吞吐量也会降低,反之亦然。通过调整缓存块的超时阈值,用户可根据需求灵活的权衡系统延迟和吞吐量。

工作原理介绍

Storm

Storm是一个免费并开源的分布式实时计算系统。利用Storm可以很容易做到可靠地处理无限的数据流,像Hadoop批量处理大数据一样,Storm可以实时处理数据。

Storm也是主从架构,主节点Nimbus负责资源分配和任务调度,工作节点Supervisor负责真正执行任务。一个Supervisor可以有多个工作进程Worker,每个工作进程中可以运行多个Task,每个Task都是一个线程,执行实际的数据处理。Task中运行的是Spout或者Bolt,前者表示的是数据源,后者表示的是消息处理单元,运行用户的程序逻辑。还有一个概念叫Topology,表示应用程序计算逻辑的拓扑结构。

avatar

Storm中每条消息的数据结构称为Tuple,每一个Tuple都是一个值的集合,值是以name, value的形式存在tuple中。

Apache Storm的主要亮点是,它是一个容错,快速,没有“单点故障”(SPOF)分布式应用程序,但是Storm不支持有状态计算

SparkStreaming

SparkStreaming是对于Spark核心API的拓展,从而支持对于实时数据流的可拓展,高吞吐量和容错性流处理。

Spark Streaming内部的基本工作原理如下:接收实时输入数据流,然后将数据拆分成多个batch,比如每收集1秒的数据封装为一个batch,然后将每个batch交给Spark的计算引擎进行处理,最后会生产出一个结果数据流,其中的数据,也是由一个一个的batch所组成的。

avatar

Spark Streaming提供了一种高级的抽象,叫做DStream,英文全称为Discretized Stream,中文翻译为“离散流”,它代表了一个持续不断的数据流。DStream的内部,其实一系列持续不断产生的RDD。RDD是Spark Core的核心抽象,即,不可变的,分布式的数据集。DStream中的每个RDD都包含了一个时间段内的数据,即DStream就是多个RDD组成的一个序列,所以SparkStreaming是以微批来模拟流,并不是一个纯实时的场景。

avatar

SparkStreaming支持有状态计算。Spark Streaming 通过 updateStateByKey 操作保存任意的状态。为使用这个功能,需要做下面两步:

  1. 定义状态,状态可以是一个任意的数据类型。

  2. 定义状态更新函数,用此函数阐明如何使用之前的状态和来自输入流的新值对状态进行更新。

updateStateByKey 操作要求必须开启Checkpoint机制。且不能是本地文件系统,必须是HDFS。

SparkStreaming的反压:SparkStreaming 从v1.5开始引入反压机制(back-pressure),由于它是微批处理,所以通过估计当前系统处理数据的速率,动态调节数据接收速率来适配集群数据处理能力(和Flink不同,Flink不需要反压)。

Flink 被设计成能用上千个点在大规模集群上运行。除了支持独立集群部署外,Flink 还支持 YARN 和Mesos 方式部署。当Flink系统启动时,首先启动JobManager和一至多个TaskManager。JobManager负责协调Flink系统,TaskManager则是执行并行程序的worker。当系统以本地形式启动时,一个JobManager和一个TaskManager会启动在同一个JVM中。

当一个程序被提交后,系统会创建一个Client来进行预处理,将程序转变成一个并行数据流的(parallel data flow)形式,交给JobManager和TaskManager执行。

avatar

Flink 保存点提供了一个状态化的版本机制,使得能以无丢失状态和最短停机时间的方式更新应用或者回退历史数据。

avatar

容错性对比

消息传输正确性保证语义

At Most Once:在框架中每条消息传输零次或者一次,也就是说,消息可能会丢失。

At Least Once:在框架中每条消息会进行多次传输尝试,至少需要有一次成功。也就是说,消息不会丢失,但可能会重复。

Exactly Once:在框架中每条消息有且只有一次,也就是说,消息既不会丢失也不会重复。这种消息传递类型是目前各大流式框架需要提供的功能。

容错性对比

Storm的容错通过ack机制实现,每个bolt或spout处理完成一条data后会发送一条ack消息给acker bolt。当该条data被所有节点都处理过后,它会收到来自所有节点ack, 这样一条data处理就是成功的。storm可以保证数据不丢失,但是只能达到at least once语义。此外,因为需要每条data都做ack,所以容错的开销很大。

Spark依赖checkpoint机制来进行容错,只要batch执行到doCheckpoint操作前挂了,那么该batch就会被完整的重新计算。spark可以保证计算过程的exactly once

Flink使用Chandy-Chandy-Lamport Algorithm 来做Asynchronous Distributed Snapshots(异步分布式快照),其本质也是checkpoint。如下图,flink定时往流里插入一个barrier(隔栏),这些barriers把数据分割成若干个小的部分,当barrier流到某个operator时,operator立即会对barrier对应的一小部分数据做checkpoint并且把barrier传给下游(checkpoint操作是异步的,并不会打断数据的处理),直到所有的sink operator做完自己checkpoint后,一个完整的checkpoint才算完成。当出现failure时,flink会从最新完整的checkpoint点开始恢复。

avatar

flink的checkpoint机制非常轻量,barrier不会打断streaming的流动,而且做checkpoint操作也是异步的。其次,相比storm需要ack每条data,flink做的是small batch的checkpoint,容错的代价相对要低很多。最重要的是flink的checkpoint机制能保证exactly once

吞吐量和延迟

吞吐量

Storm的容错机制需要对每条data进行ack,因此容错开销对吞吐量影响巨大,吞吐量下降甚至可以达到70%。所以storm在打开ack容错机制后,吞吐量下降非常明显。

Spark是mirco-batch级别的计算,各种优化做的也很好,它的吞吐量是最大的。但是需要提一下,有状态计算(如updateStateByKey算子)需要通过额外的rdd来维护状态,导致开销较大,对吞吐量影响也较大。

Flink的容错机制较为轻量,对吞吐量影响较小,而且拥有图和调度上的一些优化机制,使得flink可以达到很高的吞吐量(Flink在开启checkpoint和关闭的情况下吞吐量变化不大,说明flink的容错机制确实代价不高)。

延迟

Storm是native streaming实现,可以轻松的达到几十毫秒级别的延迟,在几款框架中它的延迟是最低的。

Spark基于micro-batch实现,提高了吞吐量,但是付出了延迟的代价。一般spark的延迟是秒级别的。

Flink也是native streaming实现,也可以达到百毫秒级别的延迟。

总结

如何选择实时框架

  1. 需要关注流数据是否需要进行状态管理

  2. At-least-once或者Exectly-once消息投递模式是否有特殊要求

  3. 对于小型独立的项目,并且需要低延迟的场景,建议使用storm

  4. 如果你的项目已经使用了spark,并且秒级别的实时处理可以满足需求的话,建议使用spark streaming

  5. 要求消息投递语义为Exactly Once的场景;数据量较大,要求高吞吐低延迟的场景;需要进行状态管理或窗口统计的场景,建议使用Flink

avatar

最后更新: 2021年02月05日 17:25

原始链接: https://jjw-story.github.io/2021/02/05/Flink Storm SparkStream对比/

× 请我吃糖~
打赏二维码